package org.xx.armory.db;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.net.URI;
import java.net.URISyntaxException;

import static org.xx.armory.commons.Validators.greaterThanOrEqual;
import static org.xx.armory.commons.Validators.notBlank;
import static org.xx.armory.commons.Validators.notNull;

public final class JedisPoolFactory {
    private static final Logger LOGGER = LoggerFactory.getLogger(JedisPoolFactory.class);

    private JedisPoolFactory() {
        throw new UnsupportedOperationException();
    }

    /**
     * 测试Redis连接池是否可用。
     *
     * @param pool
     *         待测试的连接池。
     */
    private static void testPool(
            URI uri,
            JedisPool pool
    ) {
        // 测试能否正常创建Redis连接。
        try (final Jedis jedis = pool.getResource()) {
            LOGGER.trace("echo from redis [{}]: \"{}\"", uri, jedis.echo("test jedis pool"));
        }
    }

    /**
     * 创建Jedis连接池。
     *
     * @param uri
     *         连接Redis服务器的URI。
     * @param timeout
     *         操作超时(毫秒)。
     * @return 已创建的连接池。
     * @throws IllegalArgumentException
     *         如果参数{@code uri}是{@code null}或者只包含空白字符，或者参数{@code uri}不是正确的连接Redis数据库的URI，或者参数{@code timeout}小于{@code 0}。
     */
    public static JedisPool createPool(
            String uri,
            int timeout
    ) {
        uri = notBlank(uri, "uri").trim();
        greaterThanOrEqual(timeout, "timeout", 0);

        try {
            return createPool(new URI(uri), timeout);
        } catch (URISyntaxException ex) {
            throw new IllegalArgumentException("invalid redis uri: " + uri, ex);
        }
    }

    /**
     * 创建Jedis连接池。
     *
     * @param uri
     *         连接Redis服务器的URI。
     * @param timeout
     *         操作超时(毫秒)。
     * @return 已创建的连接池。
     * @throws IllegalArgumentException
     *         如果参数{@code uri}是{@code null}或者参数{@code timeout}小于{@code 0}。
     */
    public static JedisPool createPool(
            URI uri,
            int timeout
    ) {
        notNull(uri, "uri");
        greaterThanOrEqual(timeout, "timeout", 0);

        final JedisPool pool = new JedisPool(uri, timeout);

        testPool(uri, pool);

        return pool;
    }
}
